package com.coolpad.job.device.util;

import com.coolpad.Utils.ExtAssert;
import com.coolpad.job.device.model.Point;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 将地理围栏中的所有点扫描出来
 */
@Slf4j
public class RailScanUtils {

    public static final int scan_length = 4;//小数点后四位
    private static final double scale = 0.0001;//小数点后四位


    public static List<Point> scanPoint(String polyline, String countyId) {
        String[] railStrs = polyline.split("\\|");
        List<Point> points = new ArrayList<>();
        log.info("围栏数：{}", railStrs.length);
        for (String railStr : railStrs) {
            String[] rail = railStr.split(";");
            points.addAll(scanPoint(rail,countyId));
        }
        log.info("adCode:{} 扫描全部点数:{}", countyId, points.size());
        return points;
    }

    public static List<Point> scanPoint(String[] rail, String countyId) {
        ExtAssert.noNullElements(rail,"rail is empty");
        List<Double> lats = new ArrayList<>(100);
        List<Double> lons = new ArrayList<>(100);
        List<Point> ps = new ArrayList<>(100);
        for (String pointStr : rail) {
            String[] point = pointStr.split(",");
            Double lon = Double.valueOf(point[0]);
            Double lat = Double.valueOf(point[1]);
            lons.add(lon);
            lats.add(lat);
            ps.add(new Point(lon,lat,countyId));
        }
        return scanPoint(Collections.max(lons),Collections.min(lons),Collections.max(lats),Collections.min(lats),ps,countyId);
    }

    /**
     *
     * @param maxLon
     * @param minLon
     * @param maxLat
     * @param minLat
     * @param rail 地理围栏
     * @return
     */
    private static List<Point> scanPoint(double maxLon, double minLon, double maxLat, double minLat, List<Point> rail, String countyId) {
        maxLon = NumberUtils.newScale(maxLon,scan_length);
        minLon = NumberUtils.newScale(minLon,scan_length);
        maxLat = NumberUtils.newScale(maxLat,scan_length);
        minLat = NumberUtils.newScale(minLat,scan_length);
        log.info("扫描围栏 maxLon:{}, minLon:{}, maxLat:{}, minLat:{}", maxLon, minLon, maxLat, minLat);
        List<Point> scanPs = new ArrayList<>();
        for(double lon = minLon; lon <= maxLon; lon=NumberUtils.sum(lon, scale)) {
            for(double lat = minLat; lat <= maxLat; lat=NumberUtils.sum(lat, scale)) {
                if(pointInPolygon(lon,lat,rail)) {
                    scanPs.add(new Point(lon,lat,countyId));
                }
            }
        }
        return scanPs;
    }

    public static boolean pointInPolygon (double ALon , double ALat , List<Point> ps) {
        int iSum, iCount, iIndex;
        double dLon1 = 0, dLon2 = 0, dLat1 = 0, dLat2 = 0, dLon;
        if (ps.size() < 3) {
            return false;
        }
        iSum = 0;
        iCount = ps.size();
        for (iIndex = 0; iIndex<iCount;iIndex++) {
            if (iIndex == iCount - 1) {
                dLon1 = ps.get(iIndex).getX();
                dLat1 = ps.get(iIndex).getY();
                dLon2 = ps.get(0).getX();
                dLat2 = ps.get(0).getY();
            } else {
                dLon1 = ps.get(iIndex).getX();
                dLat1 = ps.get(iIndex).getY();
                dLon2 = ps.get(iIndex + 1).getX();
                dLat2 = ps.get(iIndex + 1).getY();
            }
            // 以下语句判断A点是否在边的两端点的水平平行线之间，在则可能有交点，开始判断交点是否在左射线上
            if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
                if (Math.abs(dLat1 - dLat2) > 0) {
                    //得到A点向左射线与边的交点的x坐标：
                    dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);
                    // 如果交点在A点左侧（说明是做射线与边的交点），则射线与边的全部交点数加一：
                    if (dLon < ALon) {
                        iSum++;
                    }
                }
            }
        }
        if ((iSum % 2) != 0) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {

        double s = 43.6132;
        System.out.println(s = NumberUtils.sum(s, scale));
        System.out.println(s = NumberUtils.sum(s, scale));
    }
}
